package com.wusuowei.springboot.controller;


import cn.hutool.core.io.FileUtil;
import cn.hutool.crypto.SecureUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.wusuowei.springboot.constant.Constants;
import com.wusuowei.springboot.mapper.FileMapper;
import com.wusuowei.springboot.model.po.Files;
import com.wusuowei.springboot.utils.DateUtil;
import com.wusuowei.springboot.utils.R;
import io.swagger.annotations.Api;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.List;

/**
 * <p>
 *  前端控制器
 * </p>
 *
 * @author lgy
 */
@Slf4j
@RestController
@Api(value = "文件管理接口", tags = "文件管理接口")
@RequestMapping("file")
public class FileController {

    @Autowired
    private FileMapper fileMapper;

    @Autowired
    private RedisTemplate redisTemplate;

    @Value("${file.upload.path}")
    private String fileUploadPath;

    @PostMapping("/upload")
    public R uploadImage(@RequestParam MultipartFile file) throws Exception {

        File pFile = new File(fileUploadPath);
        if(!pFile.exists()){
            pFile.mkdirs();
        }
        String url;
        // 获取文件的md5
        String md5 = SecureUtil.md5(file.getInputStream());
        // 从数据库查询是否存在相同的记录
        Files dbFiles = getFileByMd5(md5);
        if(dbFiles != null){
            url = dbFiles.getUrl();
        }else{

            String filename = file.getOriginalFilename();
            long size = file.getSize();
            String suffix = filename.substring(filename.lastIndexOf("."));

            String fileUUID = DateUtil.getCurrentDateStr() +suffix;
            File imageFile = new File(fileUploadPath+fileUUID);
            // 上传文件到磁盘
            file.transferTo(imageFile);
            // 数据库若不存在重复文件，则不删除刚才上传的文件
            url = "http://localhost:9090/files/" + fileUUID;
            // 存储数据库
            Files saveFile = new Files();
            saveFile.setName(filename);
            saveFile.setType(suffix.replace(".",""));
            saveFile.setSize(size/1024);
            saveFile.setUrl(url);
            saveFile.setMd5(md5);
            fileMapper.insert(saveFile);
        }
        flushRedis(Constants.FILES_KEY);

        return R.ok().setData(url);

    }

    /**
     * @description 下载
     * @param fileUUID 新文件
     * @param response 回答
     *
     * @author LGY
     * @date 2023/03/27 13:20
     */
    @GetMapping("/{fileUUID}")
    public void download(@PathVariable String fileUUID, HttpServletResponse response) throws IOException {
        // 根据文件的唯一标识码获取文件
        //String parent = System.getProperty("user.dir");//项目根工程路径
       // String parentPath = parent + fileUploadPath;
        File uploadFile = new File(fileUploadPath + fileUUID);
        // 设置输出流的格式
        ServletOutputStream os = response.getOutputStream();
        response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileUUID, "UTF-8"));
        response.setContentType("application/octet-stream");

        // 读取文件的字节流
        os.write(FileUtil.readBytes(uploadFile));
        os.flush();
        os.close();
    }

    /**
     * @description 通过md5获取文件
     * @param md5 md5型
     * @return {@link Files }
     * @author LGY
     * @date 2023/03/27 13:37
     */
    private Files getFileByMd5(String md5) {
        // 查询文件的md5是否存在
        QueryWrapper<Files> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("md5", md5);
        List<Files> filesList = fileMapper.selectList(queryWrapper);
        return filesList.size() == 0 ? null : filesList.get(0);
    }


    /**
     * @description 查找页面
     * @param pageNum 书籍页码
     * @param pageSize 页面大小
     * @param name 名称
     * @return {@link R }
     * @author LGY
     * @date 2023/03/27 16:00
     */
    @GetMapping("/page")
    public R findPage(@RequestParam Integer pageNum,
                           @RequestParam Integer pageSize,
                           @RequestParam(defaultValue = "") String name) {

        QueryWrapper<Files> queryWrapper = new QueryWrapper<>();
        // 查询未删除的记录
        queryWrapper.eq("is_delete", false);
        queryWrapper.orderByDesc("id");
        if (!"".equals(name)) {
            queryWrapper.like("name", name);
        }
        return R.ok().setData(fileMapper.selectPage(new Page<>(pageNum, pageSize), queryWrapper));
    }

    /**
     * @description 更新文件
     * @param files 文件夹
     * @return {@link R }
     * @author LGY
     * @date 2023/03/27 16:10
     */
    @PostMapping("/update")
    public R update(@RequestBody Files files) {
        flushRedis(Constants.FILES_KEY);
        return R.ok().setData(fileMapper.updateById(files));
    }

    @DeleteMapping("/{id}")
    public R delete(@PathVariable Integer id) {
        fileMapper.deleteById(id);
        flushRedis(Constants.FILES_KEY);
        return R.ok();
    }
    @GetMapping("/detail/{id}")
    public R getById(@PathVariable Integer id) {
        return R.ok().setData(fileMapper.selectById(id));
    }
    @PostMapping("/del/batch")
    public R deleteBatch(@RequestBody List<Integer> ids) {
        // select * from sys_file where id in (id,id,id...)
        fileMapper.deleteBatchIds(ids);
        flushRedis(Constants.FILES_KEY);
        return R.ok();
    }

    // 设置缓存
    private void setCache(String key, String value) {
        redisTemplate.opsForValue().set(key, value);
    }

    // 删除缓存
    private void flushRedis(String key) {
        redisTemplate.delete(key);
    }
}
